package com.yanjiali.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.enums.ApiErrorCode;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.yanjiali.enumerate.LoginTypeEnum;
import com.yanjiali.feign.CommentServiceFeign;
import com.yanjiali.feign.JwtToken;
import com.yanjiali.feign.OAuth2FeignClient;
import com.yanjiali.model.GetLikeCommentListResp;
import com.yanjiali.model.R;
import com.yanjiali.model.req.LogOutReq;
import com.yanjiali.model.resp.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yanjiali.mapper.UserMapper;
import com.yanjiali.entity.User;
import com.yanjiali.service.UserService;

/**
 * @Package: com.yanjiali.service.impl
 * @Author: yanjiali
 * @Created: 2025/4/10 22:35
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{

    @Autowired
    private OAuth2FeignClient oAuth2FeignClient;

    @Autowired
    private CommentServiceFeign commentServiceFeign;

    //TODO 对应：tenseek-api:tenseek-secret 的Base64编码
    @Value("${basic.token:Basic dGVuc2Vlay1hcGk6dGVuc2Vlay1zZWNyZXQ=}")
    private String basicType;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public R<LoginResp> login(String username, String password) {
        log.info("普通用户开始登录: {}", username);

        //1、获取token 需要远程调用authorization-server 该服务
        ResponseEntity<JwtToken> tokenResponseEntity
                = oAuth2FeignClient.getToken("password", username, password, LoginTypeEnum.MEMBER_TYPE.getLoginType(), basicType);
        if(tokenResponseEntity.getStatusCode() != HttpStatus.OK) {
            throw new ApiException(ApiErrorCode.FAILED);
        }
        JwtToken jwtToken = tokenResponseEntity.getBody();
        log.info("远程调用授权服务器成功，获取的token为{}", JSON.toJSONString(jwtToken, true));
        String token = jwtToken.getAccessToken();   //获取请求体中的token
        String refreshToken = jwtToken.getRefreshToken();   //获取请求体中的refreshToken

        //2、权限数据怎么查询 -- 不需要查询 jwt中已经包含
        Jwt jwt = JwtHelper.decode(token);      // 解码给定的 JWT Token
        String jwtJsonStr = jwt.getClaims();    // 获取解码后的 JWT Token 的声明部分（Claims），返回一个字符串
        JSONObject jwtJson = JSON.parseObject(jwtJsonStr);  //获取json格式的jwt串
        JSONArray authoritiesJsonArray = jwtJson.getJSONArray("authorities");
        List<SimpleGrantedAuthority> authorities = authoritiesJsonArray.stream()
                .map(authoritiesJson -> new SimpleGrantedAuthority(authoritiesJson.toString()))
                .collect(Collectors.toList());

        //TODO 将该token存储到redis里面，配置我们的网关jwt验证操作，并设置对应的过期时间
        stringRedisTemplate.opsForValue().set(token, "", jwtToken.getExpiresIn(), TimeUnit.SECONDS);

        return R.ok(new LoginResp(token, refreshToken, authorities));

    }

    @Override
    public R<LogOutResp> logOut(LogOutReq logOutReq) {
        stringRedisTemplate.delete(logOutReq.getToken());
        return R.ok(new LogOutResp());
    }

    @Override
    public R<ObtainTheUsernameThroughTheIdResp> obtainTheUsernameThroughTheId(Long userId) {
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(userId != null, User::getId, userId);
        User user = getOne(lambdaQueryWrapper);
        if(user == null) {
            throw new IllegalArgumentException("用户id参数异常");
        }
        return R.ok(new ObtainTheUsernameThroughTheIdResp(user.getUsername()));
    }

    @Override
    public R<GetTheAvatarThroughTheUsernameResp> getTheAvatarThroughTheUsername(String username) {
        if(username == null) {
            throw new IllegalArgumentException("不合法的用户名参数");
        }
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUsername, username);
        User user = userMapper.selectOne(lambdaQueryWrapper);
        if(user == null) {
            throw new IllegalArgumentException("用户名参数异常");
        }
        return R.ok(new GetTheAvatarThroughTheUsernameResp(user.getAvatar()));
    }

    @Override
    public R<GetTheBasicInformationOfTheUserByIDResp> getTheBasicInformationOfTheUserByID(Long userId) {
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getId, userId);

        User user = getOne(lambdaQueryWrapper);
        if(user != null) {
            GetTheBasicInformationOfTheUserByIDResp getTheBasicInformationOfTheUserByIDResp = new GetTheBasicInformationOfTheUserByIDResp();
            getTheBasicInformationOfTheUserByIDResp.setUsername(user.getUsername());
            getTheBasicInformationOfTheUserByIDResp.setAvatar(user.getAvatar());
            getTheBasicInformationOfTheUserByIDResp.setLevel(user.getLevel());
            getTheBasicInformationOfTheUserByIDResp.setAddress(user.getAddress());
            return R.ok(getTheBasicInformationOfTheUserByIDResp);
        }

        throw new IllegalArgumentException("未知的用户id参数");
    }

    @Override
    public R<GetTheBasicInformationOfTheUserByIDsResp> getTheBasicInformationOfTheUserByIDs(List<Long> userIds) {
        //构造条件构造器
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(User::getId, userIds);

        //查询并封装结果
        List<User> userList = list(lambdaQueryWrapper);
        if (userList == null || userList.size() < 1) {
            R.fail("没有对应的用户数据");
        }
        Map<Long, GetTheBasicInformationOfTheUserByIDResp> userInfoMap
                = userList.stream().map(user -> {
                    GetTheBasicInformationOfTheUserByIDResp userInfo = new GetTheBasicInformationOfTheUserByIDResp();
                    userInfo.setUsername(user.getUsername());
                    userInfo.setAddress(user.getAddress());
                    userInfo.setAvatar(user.getAvatar());
                    userInfo.setLevel(user.getLevel());
                    userInfo.setUserID(user.getId());
                    return userInfo;
                }).collect(Collectors.toMap(
                        GetTheBasicInformationOfTheUserByIDResp::getUserID, // Key: userID
                        userInfo -> userInfo                               // Value: 整个对象
                ));

        return R.ok(new GetTheBasicInformationOfTheUserByIDsResp(userInfoMap));
    }

    @Override
    public R<GetTheBasicInformationOfTheCurrentUserResp> getTheBasicInformationOfTheCurrentUser() {
        //获取当前登录用户id
        String userId = "";
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if(authentication != null) {
            userId = authentication.getPrincipal().toString();
        }else {
            return R.fail("当前没有用户登录，无法获取基本信息");
        }

        //构造条件构造器
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getId, userId);

        User user = getOne(lambdaQueryWrapper);
        if(user != null) {
            GetTheBasicInformationOfTheCurrentUserResp userInfoResp = new GetTheBasicInformationOfTheCurrentUserResp();
            userInfoResp.setId(Long.valueOf(userId));
            userInfoResp.setUsername(user.getUsername());
            userInfoResp.setAvatar(user.getAvatar());
            userInfoResp.setLevel(String.valueOf(user.getLevel()));

            //TODO 远程调用获取用户点赞信息
            R<GetLikeCommentListResp> respR = commentServiceFeign.getLikeCommentList();
            if(respR.getCode() == 200) {
                List<Long> likeCommentIdList = respR.getData().getLikeCommentIdList();
                userInfoResp.setLikeIds(likeCommentIdList);
            }

            return R.ok(userInfoResp);
        }

        return R.fail("获取当前登录用户基本信息失败");
    }
}
